import re
import os
import sys
from pathlib import Path
import hashlib
import datetime

def find_all_paths(target_path, ext=None):
    paths = []
    for dirpath, dirname, filenames in os.walk(target_path):
        for filename in filenames:    
            paths.append(os.path.join(dirpath, filename))
    if ext:
        paths = [x for x in paths if x.endswith(ext)]
    return sorted(paths)


def get_md5sum(fpath):
    if not os.path.isfile(fpath):
        raise FileNotFoundError(f"{fpath} is not a file or not exists !")
    md5sum = hashlib.md5()
    with open(fpath, 'rb') as f:
        md5sum.update(f.read())
        return md5sum.hexdigest()


def file_md5_same(file1, file2):
    return get_md5sum(file1) == get_md5sum(file2)


def path_split(path):
    return list(Path(path).parts)


def del_root_dir(path, level=1):
    return os.path.join(*path_split(path)[level:])


def get_chgs(prefix_last, prefix, target_dir, save_path):
    path_last = os.path.join(prefix_last, target_dir)
    path_now = os.path.join(prefix, target_dir)
    pys_last = find_all_paths(path_last, ext='.py')
    pys = find_all_paths(path_now, ext='.py')

    pys_last_ = [del_root_dir(x) for x in pys_last]
    pys_ = [del_root_dir(x) for x in pys]
    adds = [x for x in pys_ if x not in pys_last_]
    dels = [x for x in pys_last_ if x not in pys_]
    boths = [x for x in pys_ if x in pys_last_]
    chgs = []
    for f in boths:
        if not file_md5_same(os.path.join(prefix_last, f), os.path.join(prefix, f)):
            chgs.append(f)

    adds_str = '\n' + '\n'.join(adds).strip() if len(adds) else ''
    dels_str = '\n' + '\n'.join(dels).strip() if len(dels) > 0 else ''
    chgs_str = '\n' + '\n'.join(chgs).strip() if len(chgs) > 0 else ''
    save_str = (f"{datetime.date.today().strftime('%Y%m%d')}\n"
                f"{'{:-<50}'.format(str(len(adds))+ ' adds:')}{adds_str}\n"
                f"{'{:-<51}'.format(str(len(dels))+ ' dels:')}{dels_str}\n"
                f"{'{:-<50}'.format(str(len(chgs))+ ' chgs:')}{chgs_str}")
    savedir = os.path.dirname(save_path)
    if savedir != '' and not os.path.exists(savedir):
        os.makedirs(savedir)
    with open(save_path, 'w') as f:
        f.write(save_str)

    return adds, dels, boths, chgs


def main():
    mg_path_last = sys.argv[1]
    mg_path = sys.argv[2]
    target_dir = sys.argv[3]
    save_path = sys.argv[4]
    get_chgs(mg_path_last, mg_path, target_dir, save_path)


if __name__ == "__main__":
    main()
